from  datetime import datetime
from guid import *
import cPickle
import time
import gobject
import os
from ui.uiconstants import GROUP, AVAILABLE, ADD, DELETE, PRIORITY_MEDIUM
from messaging2.ahconstants import MESSAGING_PATH
from data import db
from util.persist import *

class GroupService(gobject.GObject):
    """
        GroupService manages storage and retrieval of groups of users.
    """
    __gsignals__ = {
            # create signals that will be emitted when message received from the Flash UI
            'return_groups' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                    (gobject.TYPE_PYOBJECT,)),
            # taken care of by OPEN_OBJECT
            #'return_show_group' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
            #        (gobject.TYPE_PYOBJECT,)),
            'group_appeared' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                    (gobject.TYPE_PYOBJECT,)),
    }

    def __init__(self, db):
        """
            Initializes the GroupService
        """
        gobject.GObject.__init__( self ) 
        
        self._counter = 1       # used for creating new groups with distinct name
        
        self._db = db
    
    def addLookupNameCallback( self, lookupName ):
        """
            Method used to get the string name of the user
        """
        self.cbLookupName = lookupName

    """
        Methods that respond to UI requests
    """
    def onGetGroups(self, obj):
        """
            @return list of list of groups and members
                [[(gid,gname),(uid,uname),(uid,uname)]]
        """

        list_of_groups = self._db.getGroups()

        self.emit( 'return_groups', list_of_groups )

    def onNewGroup( self, obj, dummy ):
        """
            @param obj: L{FlashInterface}
            @param dummy: It's just a dummy int required for gobject
        """
        
        group_name = "New"+str(self._counter)
        guid = GUID(datetime.now())
        self._counter += 1
        self._db.addGroup( guid, group_name )
        
        obj.updateObject( self, {'subcommand':ADD, 'type':GROUP, 'id':guid, 'label':group_name, 'status':AVAILABLE} )

    def onShowGroup(self, obj, group_id):
        """
            Return the members of a group
            @param obj: L{FlashInterface}
            @param group_id: id of the group I am interested
        """
        group = self.getGroup( group_id )
        # group is a list of tuples.  First tuple is group information
        obj.showGroup( {'id':group_id, 'members':group[1:]} )
    
    def onAddUsersToGroup( self, obj, group_id, user_ids ):
        """
            Adds users to a group. 
            
            Convenience for getting a group, then adding a member.
            
            If group is unknown, has no effect.
            
            @param obj: the object that triggered the even 
            @type obj: FlashInterface
            @param user_ids: The list of GUIDs of the user to add to the group
            @type user_ids: List 
            @param group_id: The guid of the group to add to
            @type group_id: Number
        """        
        for u in user_ids:
            self._db.addMember( group_id, u)
 
    def onRemUsersFromGroup( self, obj, group_id, user_ids ):
        """
            Removes users from a group. 
            
            Convenience for getting a group, then removing a member.
            
            If group is unknown, has no effect.
            
            @param obj: the object that triggered the even 
            @type obj: FlashInterface
            @param user_ids: The list of GUID of the user to remove from the group
            @type user_ids: list of ids 
            @param group_ids: The guid of the group to remove from the group
            @type group_ids: Number
        """

        for u in user_ids:
            self._db.remMember( group_id, u )

    def onAddUserToGroup( self, obj, group_id, user_id ):
        """
            Adds a user to a group. 
            
            Convenience for getting a group, then adding a member.
            
            If group is unknown, has no effect.
            
            @param obj: the object that triggered the even 
            @type obj: FlashInterface
            @param user_id: GUID of the user to add to the group
            @type user_id: Number 
            @param group_id: The guid of the group to add to
            @type group_id: Number
        """
        
        self._db.addMember( group_id, user_id )
 
    def onDelUserFromGroup( self, obj, group_id, user_id ):
        """
            Removes a user to a group. 
            
            Convenience for getting a group, then removing a member.
            
            If group is unknown, has no effect.
            
            @param obj: the object that triggered the even 
            @type obj: FlashInterface
            @param user_id: UID of the user to remove from the group
            @type user_id: Number 
            @param group_ids: The guid of the group to remove from the group
            @type group_ids: Number
        """

        self._db.remMember( group_id, user_id )
                
    def onDelGroup( self, obj, group_id ):
        """
            Removes the group with the given GUID from the GroupService.
            
            If the group is unknown
            @param group_id: the GUID of the group to remove
            @type group_id: Number
        """
        
        self._db.remGroup( group_id )
          
        # Not needed any more  
        #obj.updateObject( self, {'subcommand':DELETE, 'type':GROUP, 'id':group_id} )

    def onUpdateGroupName( self, obj, group_id, name ):
        """
            Updates the name of a group
            @param group_id: guid of the group
            @type group_id: Number
            @param name: new name of the group
            @type name: String
        """
        
        self._db.updateGroup( group_id, name )
 
    """
        Methods to manage groups
    """
    
    def generateGroup( self, name, members ):
        """
            Group generated through learning that certain members have been near each other for
            a long time
            @param name: Name of group
            @type name: String
            @param members: List of members 
            @type members: List (GUID, names).
            @return GUID of created group
        """

        # TODO: need to generate group
        g_list = [ (guid, name) ]
        g_list += members 
        self.emit( 'group_appeared', g_list )
    
    def getGroups(self):
        """
            Returns all the groups owned by this GroupService
            Used for initialization
        
            @return list of all groups in the GroupService.
        """
    
        group_list = []
        db_list = self._db.getGroups()
        print db_list
        for group in db_list:
            detail = {'subcommand':ADD, 'id': group[0][0], 'type': GROUP, 'label': group[0][1], 
                               'status': AVAILABLE, 
                               'priority': PRIORITY_MEDIUM,
                               'date' : time.time() }
            group_list.append( detail )
        return group_list
    
    def getGroupDetails( self, group_id ):
        """
            Called by L{ObjectBroker} when user requests to see the group by double clicking
            on the UI.
        """
        group = self._db.getGroup( group_id )
        
        return {'type':GROUP, 'id':group_id, 'name':group[0][1], 'volume':1, 'balance':0, 'quality':1, 'members':group[1:]}

        
gobject.type_register( GroupService )

        
if __name__ == "__main__":

    def testGroup():
        g = Group('Temp', [(1,'hello'),(2,'why')])
        print g.getMembers()
        time.sleep(1)
        g.removeMember(1)
        print g.getMembers()
        time.sleep(1)
        g.addMember(3, 'johnny')
        print g.getMembers()
        time.sleep(1)
        g.addMember(3, 'holy')
        print g.getMembers()
        time.sleep(1)
        g.addMember(1, 'kate')
        print g.getMembers()
        time.sleep(1)
        
        print g.getHistoryString()
        print g.getHistoryOf(1)
        print g.getHistoryOfString(1)
        
    def testGroupService():
        def flattenGroups(groups):
            rs = ""
            for g in groups:
                rs += str(g) + "\n"
            return rs
            
        gs = GroupService()
        guid = gs.createGroup([(1,'hello'),(2,'why')])
        groups = gs.getGroups()
        #print flattenGroups(groups_
        
        
    testGroup()
    testGroupService()
    
